#include "sqlite/sqlite3.h"
#include <string>
#include <iostream>
#include <sstream>
#include <chrono>

bool buildTestData(sqlite3* db) {
    const char* insert_mail_sql = "INSERT INTO MAIL "
                              "(remote_id)"
                              " VALUES (?)";

    int count = 100000;
    sqlite3_stmt* stmt = NULL;
    if (sqlite3_prepare_v2(db, insert_mail_sql, -1, &stmt, NULL) != SQLITE_OK) {
        std::cout << sqlite3_errmsg(db) << std::endl;
        return false;
    }
    long long time1 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
    for (int i = 0; i < count; i++) {
        std::stringstream ss;
        ss << i;
        sqlite3_reset(stmt);
        sqlite3_bind_text(stmt, 1, ss.str().c_str(), ss.str().size(), SQLITE_TRANSIENT);
        sqlite3_step(stmt);
    }
    sqlite3_exec(db, "END TRANSACTION;", NULL, NULL, NULL);
    long long time2 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout << "build db cost " << time2 - time1 << " milliseconds. " << count << std::endl;
    return true;
}

void testQueryFlag(sqlite3* db) {
    const char* query_flag_sql = "select remote_id from MAIL where (flags & ?) == ?";
    sqlite3_stmt* stmt = NULL;
    if (sqlite3_prepare(db, query_flag_sql, -1, &stmt, NULL) != SQLITE_OK) {
        std::cout << sqlite3_errmsg(db) << std::endl;
        return;
    }

    long long time1 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    int count1 = 0;
    sqlite3_bind_int64(stmt, 1, 8);
    sqlite3_bind_int64(stmt, 2, 8);
    while(sqlite3_step(stmt) == SQLITE_ROW) {
        sqlite3_column_text(stmt, 1);
        count1++;
    }
    long long time2 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    int count2 = 0;
    sqlite3_reset(stmt);
    sqlite3_bind_int64(stmt, 1, 0);
    sqlite3_bind_int64(stmt, 2, 0);
    while(sqlite3_step(stmt) == SQLITE_ROW) {
        sqlite3_column_text(stmt, 1);
        count2++;
    }
    long long time3 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout << "query 1 cost " << time2 - time1 << " milliseconds. " << count1 << std::endl;
    std::cout << "query 2 cost " << time3 - time2 << " milliseconds. " << count2 << std::endl;
}

int main(int argc, const char* argv[]) {
    if (argc == 1) {
        std::cout << argv[0];
        return 1;
    }

    sqlite3 *db;
    const char *db_path = "./data/Mail.db";
    if (sqlite3_open(db_path, &db) != SQLITE_OK) {
        std::cout << sqlite3_errmsg(db) << std::endl;
        return 1;
    }

    buildTestData(db);
    // testQueryFlag(db);
    sqlite3_close(db);
    return 0;
}